$TITLE ('RTX-51 INTERRUPT HANDLING')
$SYMBOLS
$NOXREF
$NOCOND
$NOMOD51
$NORB
$PAGELENGTH(80) PAGEWIDTH(110)
;************************************************************************
;*									*
;*    R T X - 5 1  :   INTERRUPT HANDLING                               *
;*							     		*
;*----------------------------------------------------------------------*
;*                                                                      *
;*    Filename     :   RTXINT.A51                                       *
;*    Language     :   Keil A-51                                        *
;*    Dev. system  :   Keil uVision2                                    *
;*    Targetsystem :   Any system based upon 8051 up                    *
;*                                                                      *
;*    Purpose      :   Contains the common interrupt handler for all    *
;*                     RTX-51 interrupt sources.                        *
;*                     The individual interrupt sources are             *
;*                     recognized by assignment of the                  *
;*                     task_id Address direct at the vector entry.      *
;*                     (see modules RTXVECx.A51).                       *
;*								     	*
;*----------------------------------------------------------------------*
;* Rev. |  Released   | Programmer    | Comments                        *
;*----------------------------------------------------------------------*
;* 0.1  |  16.1.1990  | E. Glatz      | Changes for V3.20               *
;* 0.2  |   8.3.1991  | Th. Fischler  | Changes for V4.0                *
;*      |  15.5.1991  |               | P2-Addressing eliminated        *
;*      |  29.5.1991  |               | Reset INT-Flip-flop at the      *
;*      |             |               | beginning of the handler        *
;*      |  18.9.1991  |               | Handling of the supervisor-mode *
;*      |             |               | flag                            *
;*      |  9.10.1991  | Th. Fischler  | rtx_int_count removed           *
;* 0.3  | 14.04.1992  | Th. Fischler  | Changes for Code-Bank-Switching *
;*      |             |               | support                         *
;*      |  4.06.1992  |               | RTXINS.INC converted to proc.   *
;* 0.4  | 27.10.1992  | Th. Fischler  | Reading P2 problems solved      *
;* 5.00 | 12.10.1994  | E. Glatz      | SEM_DEQUEUE added               *
;* 7.00 | 13.11.2001  | T. Mueller    | Page addressing configurable    *
;************************************************************************
;*    Copyright 1991 .. 2001 METTLER  &  FUCHS  AG,  CH-8953 Dietikon   *
;************************************************************************

$INCLUDE (RTXDEBUG.INC)
$INCLUDE (RTXIMASK.INC)

;*----------------------------------------------------------------------*
;*	I M P O R T S
;*----------------------------------------------------------------------*

$INCLUDE (RTXCONST.INC)
$INCLUDE (RTXEXTRN.INC)

;        FROM RTXDISP
EXTRN    CODE  (?RTX_REDISPATCH)            ; Dispatcher entry point

;        FROM RTXQUOP
EXTRN    CODE  (?RTX_INTSIG_DEQUEUE, ?RTX_TMO_DEQUEUE)
EXTRN    CODE  (?RTX_MSG_DEQUEUE, ?RTX_SEM_DEQUEUE)

;        FROM RTXCONF
EXTRN    DATA  (?RTX_SAVE_INT_BANK, ?B_CURRENTBANK, ?RTX_PAGE_OUT_REG)
EXTRN    CODE  (?RTX_SWITCHBANK)

;        FROM RTXINS
EXTRN    CODE  (?RTX_INSERT_RDY_PRIO)



;*----------------------------------------------------------------------*
;*	E X P O R T S
;*----------------------------------------------------------------------*

PUBLIC  ?RTX_INT_HANDLER, ?RTX_RESET_I_F_F


;*----------------------------------------------------------------------*
;*	P R O C E D U R E S
;*----------------------------------------------------------------------*
	
;*----------------------------------------------------------------------*
;*      I N T _ H A N D L E R
;*----------------------------------------------------------------------*
;*      The vector entries are contained in the files RTXVECx.VEC, all
;*      interrupts to be handled under RTX-51 use this global handler.
;*      ISR-Handlers are called directly.
;*
;*      Use of temp. variables:         ?RTX_TMP0: for interrupttask id
;*                                      ?RTX_TMP1: to save ACC
;*                                      ?RTX_TMP2: to save R0
;*                                      ?RTX_TMP3: to save R1
;*                                      ?RTX_TMP4: to save PSW
;*                                      ?RTX_TMP5: to save DPH
;*                                      ?RTX_TMP6: to save DPL
;*----------------------------------------------------------------------*
;*      Input:   - old ACC is saved in ?RTX_TMP1
;*                 ACC points to LOW(INTx_TID)
;*
;*      Output:  - 
;*----------------------------------------------------------------------*

?RTX?INT_HANDLER?RTXINT  SEGMENT CODE
                         RSEG    ?RTX?INT_HANDLER?RTXINT

?RTX_INT_HANDLER:
               DBG_SYS_ENTRY
               RTX_EXCLUDE_INT
               DBG_BUSY

               ; Reset hardware prio. flip-flop
               CALL  ?RTX_RESET_I_F_F

               MOV   ?RTX_TMP2, R0              ; Save R0,R1,DPH,DPL and PSW
               MOV   ?RTX_TMP3, R1              ; ACC alrady saved by RTXVEC#
               MOV   ?RTX_TMP4, PSW
               MOV   ?RTX_TMP5, DPH
               MOV   ?RTX_TMP6, DPL

               MOV   DPL, A

               ; Get task id from int. table and store in ?RTX_TMP0
               MOV   DPH, #HIGH(?RTX_INT_TID_TABLE_BASE)
               ; DPTR-->int_tid[vector no]
               MOVX  A, @DPTR                   ; Get int. task_id from table
               MOV   ?RTX_TMP0, A

               ; Set up ptr to state_table[task no]
               ANL   A, #01FH
               RL    A
               RL    A
               ADD   A, #LOW(?RTX_STATE_TABLE)
               MOV   DPL, A                     ; DPTR-->state_table[task_no]
                                                ; ?RTX_TMP0 contains task id
               CALL  ?RTX_TMO_DEQUEUE
                                                ; DPTR, ?RTX_TMP0 preserved
               CALL  ?RTX_INTSIG_DEQUEUE
                                                ; DPTR, ?RTX_TMP0 preserved
               CALL  ?RTX_MSG_DEQUEUE
               JZ    MSGDEQDONE                 ; Eval ret code if deq done
                                                ; DPTR preserved if no deq done
               CALL  ?RTX_SEM_DEQUEUE           ; ?RTX_TMP0 preserved
MSGDEQDONE:
                                                ; Dequeueing done
;
;       Depending on task type and execution mode, one of the following
;       actions will be performed:
;       a) int.task = fast task (driver task), systemclockhandler was 
;          executing:
;          Suspend systemclockhandler & start driver task
;       b) int.task = fast task (driver task), standarda task (non driver task)
;          was executing:
;          Suspend non driver & start driver task
;       c) int.task = fast task (driver task), processor was idle:
;          Start fast task task immediatley
;       d) int.task = standard task (non driver task), standard taskr was 
;          executing
;          Insert int. task in ready list & enter dispatcher
;       e) int.task = standard task (non driver task), processor was idle:
;          Insert int. task in ready list & enter dispatcher
;
               JNB   ?RTX_TMP0.4, NON_DRIVER
               JMP   DRIVER

NON_DRIVER:    ; Insert standard task (=non driver task) in ready list
               MOV   A, ?RTX_TMP0
               CALL  ?RTX_INSERT_RDY_PRIO
               ; Store return status in tasks context
               MOV   A, ?RTX_TMP0               ; restore int-task ID
               ANL   A, #0FH
               MOV   R0, A
               MOV   A, #LOW(?RTX_KNTXT_PTR_TABLE)
               ADD   A, R0
               ADD   A, R0
               MOV   DPL, A
               MOV   DPH, #HIGH(?RTX_KNTXT_PTR_TABLE)
               MOVX  A, @DPTR
               MOV   R0, A
               INC   DPL
               MOVX  A, @DPTR
               MOV   DPH, R0
               MOV   DPL, A

               MOV   A, #INT_EVENT
               INC   DPL
               MOVX  @DPTR, A                   ; Store return-status to r7
               ; Restore A, R0, R1, DPH, DPL and PSW
               MOV   A, ?RTX_TMP1
               MOV   R0, ?RTX_TMP2
               MOV   R1, ?RTX_TMP3
               MOV   PSW, ?RTX_TMP4
               MOV   DPH, ?RTX_TMP5
               MOV   DPL, ?RTX_TMP6

               ; If reasign use full context
               SETB  ?RTX_FULL_CONTEXT

               ; Because any standard task may interrupt any other stnadrad task
               ; (regardless of priority) we must redispatch
               LJMP  ?RTX_REDISPATCH

DRIVER:        ; Check if systemclockhandler is running (requires reasign)
               JB    ?RTX_SYSCLK_ISR, REDISPATCH_FAST
               ; Check if idle for immediate assign (without reasign)
               JNB   ?RTX_PROCESSOR_ALLOCATED, ASSIGN_FAST

REDISPATCH_FAST:
               ; Reasign interrupted task or systemclockhandler
               MOV   R0, ?RTX_TMP2              ; Restore R0
               MOV   R1, ?RTX_TMP3              ; Restore R1

              ; Only the processor registers have to be saved, because we
              ; use a different register bank and a different stack !
RESIGN_FAST:   MOV   ?RTX_SAVE_INT_A, ?RTX_TMP1
               MOV   ?RTX_SAVE_INT_B, B
               MOV   ?RTX_SAVE_INT_DPL, ?RTX_TMP6
               MOV   ?RTX_SAVE_INT_DPH, ?RTX_TMP5
               MOV   ?RTX_SAVE_INT_PSW, ?RTX_TMP4
               MOV   C, ?RTX_SUPERVISOR_MODE
               MOV   ?RTX_SAVE_INT_SV, C
               MOV   ?RTX_SAVE_INT_SP, SP
               MOV   ?RTX_SAVE_INT_RSP, ?RTX_P2_MIR
               MOV   ?RTX_SAVE_INT_RSP+1, ?RTX_PBP
               JNB   ?RTX_BANKSW, NO_BANKSW
               MOV   ?RTX_SAVE_INT_BANK, ?B_CURRENTBANK
NO_BANKSW:     MOV   ?RTX_SAVE_INT_TID, ?RTX_RUNNING_TID

               ; Start fast task (=driver task)
ASSIGN_FAST:   ; Now allocated regardless of prior state
               SETB  ?RTX_PROCESSOR_ALLOCATED

               JB    ?RTX_TMP0.1, ASSIGN_DRV3   ; Each fast task needs its own
               JB    ?RTX_TMP0.0, ASSIGN_DRV2   ; handling

               ; Start fast task 1: select reg. bank 1, set supervisor_mode=0
ASSIGN_DRV1:   MOV   PSW, #08H
               CLR   ?RTX_SUPERVISOR_MODE
               MOV   R0, #?RTX_FTASKDATA?1
               JMP   ASS_DR
               ; Start fast task 2: select reg. bank 2, set supervisor_mode=0
ASSIGN_DRV2:   MOV   PSW, #10H
               CLR   ?RTX_SUPERVISOR_MODE
               MOV   R0, #?RTX_FTASKDATA?2
               JMP   ASS_DR
               ; Start fast task 3: select reg. bank 3, set supervisor_mode=0
ASSIGN_DRV3:   MOV   PSW, #18H
               CLR   ?RTX_SUPERVISOR_MODE
               MOV   R0, #?RTX_FTASKDATA?3

ASS_DR:        MOV   SP, @R0                    ; Load the Stack-Pointer
               JNB   ?RTX_REENTRANTFLAG, NOT_R
               GLOBAL_INT_DISABLE
               INC   R0
               MOV   ?RTX_PAGE_OUT_REG, @R0
               MOV   ?RTX_P2_MIR, @R0
               INC   R0
               MOV   ?RTX_PBP, @R0
               GLOBAL_INT_ENABLE
               JMP   CHK_B
NOT_R:         INC   R0
               INC   R0                         ; R0 shows to the banknumber

CHK_B:         JNB   ?RTX_BANKSW, CONT
               INC   R0
               MOV   A, @R0
               GLOBAL_INT_DISABLE
               CALL  ?RTX_SWITCHBANK
               GLOBAL_INT_ENABLE

               ; New running task is interrupt task
CONT:          MOV   ?RTX_RUNNING_TID, ?RTX_TMP0
						
               $IF (DBG = 02H)
                  MOV   DPTR, #?RTX_DEBUG_TID   ; Store ?RTX_RUNNING_TID at
                  MOV   A, ?RTX_TMP0            ; ext. RAM addr. for debugging
                  MOVX    @DPTR, A
               $ENDIF
               ; Set up return status
               MOV   R7, #INT_EVENT
               DBG_SYS_EXIT                     ; Do not allow interrupts !
               RET


;*----------------------------------------------------------------------*
;*      R E S E T _ I _ F _ F
;*----------------------------------------------------------------------*
;*      Reset hardware interrupt priority flip-flop. There is no other
;*      instruction available to do it.
;*----------------------------------------------------------------------*
;*      Input:	 - 
;*      Output:  - 
;*----------------------------------------------------------------------*

?RTX?RESET_I_F_F?RTXINT  SEGMENT CODE
                         RSEG    ?RTX?RESET_I_F_F?RTXINT

?RTX_RESET_I_F_F:    RETI
						
;
;   END OF MODULE
;
	END
